#include "Processtree.h"
#include <sys/socket.h>

ProcessTree::ProcessTree(const std::string &jsonFile)
{
    std::ifstream file(jsonFile);
    file >> processTreeJson;
    file.close();

    parseProcessTree();
}

void ProcessTree::parseProcessTree()
{
    Json::Value processTree = processTreeJson["ProcessTree"];

    for (const auto &node : processTree)
    {
        ProcessNode newNode;
        newNode.ID = node["ID"].asInt();
        newNode.CName = node["CName"].asString();
        newNode.Name = node["Name"].asString();
        newNode.Parameter = node["Parameter"];
        newNode.Parent = node["Parent"].asInt();
        for (const auto &child : node["Children"])
            newNode.Children.push_back(child.asInt());
        nodes.emplace(node["ID"].asInt(), newNode);
    }
}

void ProcessTree::executeNode(int nodeId)
{
    ProcessNode &currentNode = nodes[nodeId];
    std::cout << "Executing Node: " << currentNode.Name << std::endl;

    int key = ImageHandleNum.at(currentNode.Name);
    switch (key)
    {
    case int(1):
    {
        results[nodeId] = camera.GetOneFrame();
        break;
    }
    case int(2):
    {
        Json::Value root = currentNode.Parameter;
        int thresh = 127, maxval = 255;
        if (root.isMember("Thresh") && root.isMember("Maxval"))
        {
            thresh = root["Thresh"].asInt();
            maxval = root["Maxval"].asInt();
        }
        results[nodeId] = ImageHandle().Binarization(boost::get<cv::Mat>(results[currentNode.Parent]), thresh, maxval);
        break;
    }
    case int(3):
    {
        Json::Value root = currentNode.Parameter;
        double alpha = 1.1, beta = 0;
        if (root.isMember("Alpha") && root.isMember("Beta"))
        {
            alpha = root["Alpha"].asDouble();
            beta = root["Beta"].asDouble();
        }
        results[nodeId] = ImageHandle().BrightnessEnforce(boost::get<cv::Mat>(results[currentNode.Parent]), alpha, beta);
        break;
    }
    case int(4):
    {
        results[nodeId] = ImageHandle().Color2Gray(boost::get<cv::Mat>(results[currentNode.Parent]));
        break;
    }
    case int(5):
    {
        Json::Value root = currentNode.Parameter;
        std::vector<cv::Vec3f> circles;
        cv::Rect roiRect;

        cv::Mat img_raw = boost::get<cv::Mat>(results[currentNode.Parent]).clone();
        cv::Mat img = img_raw.clone();

        // 配置圆查找参数
        int minDist = root["MinDist"].asInt();        // 检测到的圆之间的最小距离 大于1的整数
        int Canny_param = root["CannyParam"].asInt(); // Canny边缘检测阈值 1-255
        int hough_param = root["HoughParam"].asInt(); // 霍夫变换中圆心累加器的阈值 大于1
        int minRadius = root["MinRadius"].asInt();    // 检测到的圆的最小半径
        int maxRadius = root["MaxRadius"].asInt();    // 检测到的圆的最大半径

        if (root.isMember("ROI"))
        {
            // 计算缩放比例
            double scaleWidth =
                static_cast<double>(getCamWHParam("WidthValue")) / IMAGE_SIZE.width;
            double scaleHeight =
                static_cast<double>(getCamWHParam("HeightValue")) / IMAGE_SIZE.height;
            roiRect = cv::Rect(cvRound(root["ROI"]["X"].asInt() * scaleWidth), cvRound(root["ROI"]["Y"].asInt() * scaleHeight),
                               cvRound(root["ROI"]["Width"].asInt() * scaleWidth), cvRound(root["ROI"]["Height"].asInt() * scaleHeight));
            img = img(roiRect);
        }

        results[nodeId] = ImageHandle().CircleRecognition(img_raw, roiRect, img, circles, minDist, Canny_param,
                                                          hough_param, minRadius, maxRadius);
        break;
    }
    case int(6):
    {
        Json::Value root = currentNode.Parameter;
        cv::Rect roiRect;

        cv::Mat img_raw = boost::get<cv::Mat>(results[currentNode.Parent]).clone();
        cv::Mat img = img_raw.clone();

        int ThresholdValue1, ThresholdValue2, MinArea, MaxArea;

        if (root.isMember("ThresholdValue1") && root.isMember("ThresholdValue2") && root.isMember("MinArea") && root.isMember("MaxArea"))
        {
            ThresholdValue1 = root["ThresholdValue1"].asInt();
            ThresholdValue2 = root["ThresholdValue2"].asInt();
            MinArea = root["MinArea"].asInt();
            MaxArea = root["MaxArea"].asInt();
        }

        if (root.isMember("ROI"))
        {
            // 计算缩放比例
            double scaleWidth =
                static_cast<double>(getCamWHParam("WidthValue")) / IMAGE_SIZE.width;
            double scaleHeight =
                static_cast<double>(getCamWHParam("HeightValue")) / IMAGE_SIZE.height;
            roiRect = cv::Rect(cvRound(root["ROI"]["X"].asInt() * scaleWidth), cvRound(root["ROI"]["Y"].asInt() * scaleHeight),
                               cvRound(root["ROI"]["Width"].asInt() * scaleWidth), cvRound(root["ROI"]["Height"].asInt() * scaleHeight));
            img = img(roiRect);
        }

        DetectionResult result = ImageHandle().RectangleRecognition(img,
                                                                    ThresholdValue1,
                                                                    ThresholdValue2,
                                                                    MinArea,
                                                                    MaxArea);
        updateDetectionResult(result, img_raw, roiRect);
        results[nodeId] = result;

        break;
    }
    case int(7):
    {
        Json::Value root = currentNode.Parameter;

        cv::Rect roiRect;
        cv::Mat img_raw = boost::get<cv::Mat>(results[currentNode.Parent]).clone();
        cv::Mat img = img_raw.clone();
        cv::Mat templ;

        if (!root.isMember("TemplateId"))
        {
            break;
        }
        std::string TemplateId = root["TemplateId"].asString();
        std::string template_path = SaveImageFloderPath + TemplateId + ".jpg";

        // 使用 std::ifstream 尝试打开文件
        std::ifstream fileStream(template_path);
        if (fileStream.good())
        {
            // 如果文件成功打开，表示文件存在
            fileStream.close(); // 关闭文件流
            templ = cv::imread(template_path);
        }

        if (root.isMember("ROI"))
        {
            // 计算缩放比例
            double scaleWidth =
                static_cast<double>(getCamWHParam("WidthValue")) / IMAGE_SIZE.width;
            double scaleHeight =
                static_cast<double>(getCamWHParam("HeightValue")) / IMAGE_SIZE.height;
            roiRect = cv::Rect(cvRound(root["ROI"]["X"].asInt() * scaleWidth), cvRound(root["ROI"]["Y"].asInt() * scaleHeight),
                               cvRound(root["ROI"]["Width"].asInt() * scaleWidth), cvRound(root["ROI"]["Height"].asInt() * scaleHeight));
            img = img(roiRect);
        }

        // DetectionResult result = ImageHandle().PatternRecognition(img);
        // updateDetectionResult(result, img_raw, roiRect);
        // results[nodeId] = result;

        break;
    }
    case int(8):
    {
        std::vector<cv::Point2f> value = boost::get<DetectionResult>(results[currentNode.Parent]).coordinates;
        std::vector<cv::Point2f> RealLifeCorrd;
        for (std::vector<cv::Point2f>::const_iterator it = value.begin(); it != value.end(); ++it)
        {
            RealLifeCorrd.push_back(cv::Point2f(Affine[0][0] * it->x + Affine[0][1] * it->y + Affine[0][2], Affine[1][0] * it->x + Affine[1][1] * it->y + Affine[1][2]));
        }
        results[nodeId] = RealLifeCorrd;
        break;
    }
    case int(9):
    {
        std::vector<cv::Point2f> RealLifeCorrd = boost::get<std::vector<cv::Point2f>>(results[currentNode.Parent]);

        if (!RealLifeCorrd.empty())
        {
            std::vector<cv::Point2f>::const_iterator it = RealLifeCorrd.begin();
            std::ostringstream oss;
            oss << "##," << it->x << "," << it->y << "," << RobotCalibrationZ << ","
                << (RobotCalibrationA * 180 / M_PI) << "," << (RobotCalibrationB * 180 / M_PI) << "," << (RobotCalibrationC * 180 / M_PI) << ",1,$";
            std::string CommunicationStringData = oss.str();
            send(Communication_fd, CommunicationStringData.data(), CommunicationStringData.size(), 0);
        }
        else
        {
            std::ostringstream oss;
            oss << "##,1,1,1,1,1,1,0,$";
            std::string CommunicationStringData = oss.str();
            send(Communication_fd, CommunicationStringData.data(), CommunicationStringData.size(), 0);
        }

        break;
    }
    default:
        break;
    }

    for (int childId : currentNode.Children)
    {
        executeNode(childId);
    }
}

std::map<int, VariantType> ProcessTree::execute()
{
    executeNode(0);
    return results;
}
